from inspect import isclass
from typing import Optional, Dict, Any

from llvmlite import ir


class BuiltinFunction:
    def __init__(self, module: ir.Module = None):
        self.module = module
        self.func: Optional[ir.Function] = None
        self.register()

    def register(self):
        raise NotImplementedError

    def call(self, builder: ir.IRBuilder, args, name: str = ""):
        return builder.call(self.func, args, name)

    def __call__(self, builder: ir.IRBuilder, args, name: str = ""):
        return self.call(builder, args, name)

def get_builtin_function_cls(globals_: Dict[str, Any]):
    """
    Pass globals() to this function, to get subclasses of `PMBuiltinFunction`.

    :param globals_:
    :return:
    """
    return [v for k, v in globals_.items() if (isclass(v) and
                                               issubclass(v, BuiltinFunction) and (v != BuiltinFunction))]
